package com.zhangtai.Neusoft.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.zhangtai.Neusoft.constVo.EmployeeInfoConst;
import com.zhangtai.Neusoft.dto.PaySlipDto;
import com.zhangtai.Neusoft.vo.AwardApplicantVo;
import com.zhangtai.Neusoft.vo.SalaryGroupVo;
import com.zhangtai.modules.dao.AwardApplicantDao;
import com.zhangtai.modules.dao.AwardInfoDao;
import com.zhangtai.modules.dao.SalaryDistributionDao;
import com.zhangtai.modules.entity.employee.EmployeeInfoEntity;
import com.zhangtai.modules.entity.salary.AwardApplicantEntity;
import com.zhangtai.modules.entity.salary.AwardInfoEntity;
import com.zhangtai.modules.entity.salary.SalaryDistributionEntity;
import com.zhangtai.modules.service.employee.EmployeeInfoService;
import com.zhangtai.mq.MessageSender;
import com.zhangtai.mq.config.EmployeeInfoMqConfig;
import com.zhangtai.utils.DateUtils;
import com.zhangtai.utils.NeuAES;
import com.zhangtai.utils.R;
import com.zhangtai.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 调用ehr同步接口
 */
@RestController
public class NeuEmployeeSalaryService {
    @Autowired
    private RestTemplate restTemplate;

    @Value("${neu.applyUrl}")
    private String neuUrl;

    @Autowired
    private SalaryDistributionDao salaryDistributionDao;
    @Autowired
    private EmployeeInfoService employeeInfoService;
    @Autowired
    private MessageSender messageSender;
    @Autowired
    private EmployeeInfoMqConfig employeeInfoMqConfig;
    @Autowired
    private AwardInfoDao awardInfoDao;
    @Autowired
    private AwardApplicantDao awardApplicantDao;


    public R getEmployeeWage(String code, String yymm, String endyymm) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("empCode", code);
        jsonObject.put("yymm", yymm);
        jsonObject.put("endyymm", endyymm);
        return send(jsonObject, EmployeeInfoConst.EMPLOYEE_WAGE_URL, true);
    }

    /**
     * /薪资组分配   保存到ehr
     *
     * @param ids
     * @return
     */
    public R saveSalaryGroup(List<Long> ids) {
        //亲属关系
        List<SalaryGroupVo> salaryGroupVoList = new ArrayList<>();
        for (Long id : ids) {
            SalaryDistributionEntity entity = salaryDistributionDao.selectById(id);
            EmployeeInfoEntity employeeInfoEntity = employeeInfoService.getByIdE(entity.getOid());
            SalaryGroupVo vo = new SalaryGroupVo();
            vo.setEmpCode(employeeInfoEntity.getCode());
            vo.setGroupId(entity.getSalaryGroupId() + "");
            vo.setOperatorCode(entity.getDistributionCode());
            vo.setPayUnitId(entity.getPayrollUnitId() + "");
            vo.setBeginDate(DateUtils.format(entity.getDistributionTime()));
            salaryGroupVoList.add(vo);
        }
        sendMq(salaryGroupVoList, EmployeeInfoConst.EMPLOYEE_SALARYGROUP, "salaryGroupVOs", true);
        return R.ok();
    }


    /**
     * //注销薪资组
     * @param ids
     * @return
     */
    public R LogoutSalary(List<Long> ids){
        List<SalaryGroupVo> salaryGroupVoList=new ArrayList<>();
        for (Long id : ids) {
            SalaryDistributionEntity entity = salaryDistributionDao.selectById(id);
            EmployeeInfoEntity employeeInfoEntity = employeeInfoService.getByIdE(entity.getOid());
            SalaryGroupVo salaryGroupVo = new SalaryGroupVo();
            salaryGroupVo.setEmpCode(employeeInfoEntity.getCode());
            salaryGroupVo.setGroupId(entity.getSalaryGroupId()+"");
            salaryGroupVo.setEndDate(DateUtils.format(entity.getDistributionTime()));
            salaryGroupVoList.add(salaryGroupVo);
        }
        sendMq(salaryGroupVoList, EmployeeInfoConst.EMPLOYEE_SALARY_LOGOUT,"salaryGroupVOs",true);
        return R.ok();
    }


    /**
     * //个人奖罚保存   保存到ehr
     *
     * @param ids
     * @return
     */
    public R saveAwardApplicant(List<Long> ids) {
        //亲属关系
        List<AwardApplicantVo> awardApplicantVoList = new ArrayList<>();
        for (Long id : ids) {
            AwardInfoEntity entity = awardInfoDao.selectById(id);
            EmployeeInfoEntity employeeInfoEntity = employeeInfoService.getByIdE(entity.getOid());
            AwardApplicantEntity awardApplicantEntity = awardApplicantDao.selectById(entity.getDistributionId());
            AwardApplicantVo vo = new AwardApplicantVo();
            AwardApplicantVo vo1 = new AwardApplicantVo();
            vo.setEmpName(employeeInfoEntity.getName());
            vo1.setEmpName(employeeInfoEntity.getName());
            vo.setEmpCode(employeeInfoEntity.getCode());
            vo1.setEmpCode(employeeInfoEntity.getCode());
            vo.setApplyCode(awardApplicantEntity.getUsercode());
            vo1.setApplyCode(awardApplicantEntity.getUsercode());
            vo.setRpDate(DateUtils.format(entity.getCreateTime()));
            vo1.setRpDate(DateUtils.format(entity.getCreateTime()));
            vo.setRpItem(awardApplicantEntity.getAwardName());
            vo1.setRpItem(awardApplicantEntity.getAwardName());
            if (1 == entity.getAwardType()) {
                vo.setRpMoney(entity.getAmountOne().negate());
                vo1.setRpMoney(entity.getAmountTwo().negate());
            } else {
                vo.setRpMoney(entity.getAmountOne());
                vo1.setRpMoney(entity.getAmountTwo());
            }
            vo.setPperiod(DateUtils.format(entity.getMonthOne()));
            vo1.setPperiod(DateUtils.format(entity.getMonthTwo()));
            vo.setImplementStatus("1");
            vo1.setImplementStatus("1");
            vo.setXmlb(awardApplicantEntity.getType() + "");
            vo1.setXmlb(awardApplicantEntity.getType() + "");
            vo.setRemark(awardApplicantEntity.getRemark());
            vo1.setRemark(awardApplicantEntity.getRemark());
            if (vo.getRpMoney().compareTo(BigDecimal.ZERO) != 0)
                awardApplicantVoList.add(vo);
            if (vo1.getRpMoney().compareTo(BigDecimal.ZERO) != 0)
                awardApplicantVoList.add(vo1);
        }
        sendMq(awardApplicantVoList, EmployeeInfoConst.EMPLOYEE_AWARD, "rpResultVOS", true);
        return R.ok();
    }

    public void sendMq(Object object, String type, String className, boolean isArray) {
        JSONObject obj = new JSONObject();
        if (isArray) {
            JSONArray jsonArray = JSONArray.parseArray(JSON.toJSON(object).toString());
            obj.put(className, jsonArray);
        } else {
            JSONObject jsonObject = JSONObject.parseObject(JSON.toJSON(object).toString());
            obj.put(className, jsonObject);
        }
        obj.put("type", type);
        messageSender.send(employeeInfoMqConfig.SMS_EXCHANGE, employeeInfoMqConfig.SMS_ROUTING_KEY, obj.toJSONString());
    }


    private R send(JSONObject jsonObject, String path, Boolean flag) {
        String token = NeuAES.getToken();
        String url = neuUrl + path;
        jsonObject.put("clientToken", token);
        HttpHeaders httpHeaders = new HttpHeaders();
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(jsonObject,httpHeaders);
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url, httpEntity, JSONObject.class);
        JSONObject body = responseEntity.getBody();
        if (ObjectUtils.isEmpty(body)) {
            return R.error();
        }
        Boolean success = body.getBoolean("success");
        if (!success || ObjectUtils.isEmpty(success)) {
            return R.error();
        }
        String message = body.getString("message");
        if (StringUtils.isEmpty(message)) {
            return R.error();
        }
        if (flag) {
            JSONObject str = body.getJSONObject("payslip");
            HashMap map = new HashMap();
            List<PaySlipDto> list = resultList(str.toString());
            map.put("list", list);
            map.put("sum", sumPaySlipList(list));
            return R.ok(map);
        }
        return R.ok(body.getString("payslip"));
    }

    private List<PaySlipDto> resultList(String str) {
        Map map = (Map) JSONObject.parse(str);
        NeuAES neuAES = new NeuAES();
        String password = "rort*94MttHat!1@";
        neuAES.setPwd(password);
        List<PaySlipDto> list = new ArrayList<>();
        map.forEach((key, value) -> {
            PaySlipDto dto = new PaySlipDto();
            Map m = (Map) JSONObject.parse(value.toString());
            m.forEach((k, v) -> {
                switch (k.toString()) {
                    case "发放月份":
                        dto.setMonth(v.toString());
                        break;
                    case "加班工资":
                        dto.setOvertimePay(neuAES.decode(v.toString()));
                        break;
                    case "扣款合计":
                        dto.setTotalDeduction(neuAES.decode(v.toString()));
                        break;
                    case "绩效工资":
                        dto.setPerformancePay(neuAES.decode(v.toString()));
                        break;
                    case "竞业津贴":
                        dto.setCompetitionAllowance(neuAES.decode(v.toString()));
                        break;
                    case "养老保险":
                        dto.setEndowmentInsurance(neuAES.decode(v.toString()));
                        break;
                    case "医保":
                        dto.setMedicalInsurance(neuAES.decode(v.toString()));
                        break;
                    case "交通补贴":
                        dto.setTransportationSubsidy(neuAES.decode(v.toString()));
                        break;
                    case "其他":
                        dto.setOthers(neuAES.decode(v.toString()));
                        break;
                    case "补充社保津贴":
                        dto.setSociaSecurityAllowance(neuAES.decode(v.toString()));
                        break;
                    case "公积金":
                        dto.setProvidentFund(neuAES.decode(v.toString()));
                        break;
                    case "失业保险":
                        dto.setUnemploymentInsurance(neuAES.decode(v.toString()));
                        break;
                    case "奖金":
                        dto.setBonus(neuAES.decode(v.toString()));
                        break;
                    case "预发奖金":
                        dto.setAdvanceBonus(neuAES.decode(v.toString()));
                        break;
                    case "应发工资":
                        dto.setSalaryPayable(neuAES.decode(v.toString()));
                        break;
                    case "社保津贴":
                        dto.setSocialSecurityAllowance(neuAES.decode(v.toString()));
                        break;
                    case "个人所得税":
                        dto.setPersonalIncomeTax(neuAES.decode(v.toString()));
                        break;
                    case "税后扣款":
                        dto.setDeductionAfterTax(neuAES.decode(v.toString()));
                        break;
                    case "通讯补贴":
                        dto.setCommunicationSubsidy(neuAES.decode(v.toString()));
                        break;
                    case "职称津贴":
                        dto.setTitleAllowance(neuAES.decode(v.toString()));
                        break;
                    case "基本工资":
                        dto.setBasicWage(neuAES.decode(v.toString()));
                        break;
                    case "补扣预发奖金":
                        dto.setDeductionOfAdvanceBonus(neuAES.decode(v.toString()));
                        break;
                    case "实发工资":
                        dto.setPaidInSalary(neuAES.decode(v.toString()));
                        break;
                    case "纯粹工资":
                        dto.setNetWage(neuAES.decode(v.toString()));
                        break;
                }
            });
            list.add(dto);
        });
        return list;
    }

    private PaySlipDto sumPaySlipList(List<PaySlipDto> list) {
        PaySlipDto dto = new PaySlipDto();
        dto.setOvertimePay(list.stream().map(t -> new BigDecimal(t.getOvertimePay())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setTotalDeduction(list.stream().map(t -> new BigDecimal(t.getTotalDeduction())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setPerformancePay(list.stream().map(t -> new BigDecimal(t.getPerformancePay())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setCompetitionAllowance(list.stream().map(t -> new BigDecimal(t.getCompetitionAllowance())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setEndowmentInsurance(list.stream().map(t -> new BigDecimal(t.getEndowmentInsurance())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setMedicalInsurance(list.stream().map(t -> new BigDecimal(t.getMedicalInsurance())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setTransportationSubsidy(list.stream().map(t -> new BigDecimal(t.getTransportationSubsidy())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setOthers(list.stream().map(t -> new BigDecimal(t.getOthers())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setSociaSecurityAllowance(list.stream().map(t -> new BigDecimal(t.getSociaSecurityAllowance())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setProvidentFund(list.stream().map(t -> new BigDecimal(t.getProvidentFund())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setUnemploymentInsurance(list.stream().map(t -> new BigDecimal(t.getUnemploymentInsurance())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setBonus(list.stream().map(t -> new BigDecimal(t.getBonus())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setAdvanceBonus(list.stream().map(t -> new BigDecimal(t.getAdvanceBonus())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setSalaryPayable(list.stream().map(t -> new BigDecimal(t.getSalaryPayable())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setSocialSecurityAllowance(list.stream().map(t -> new BigDecimal(t.getSocialSecurityAllowance())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setPersonalIncomeTax(list.stream().map(t -> new BigDecimal(t.getPersonalIncomeTax())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setDeductionAfterTax(list.stream().map(t -> new BigDecimal(t.getDeductionAfterTax())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setCommunicationSubsidy(list.stream().map(t -> new BigDecimal(t.getCommunicationSubsidy())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setTitleAllowance(list.stream().map(t -> new BigDecimal(t.getTitleAllowance())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setBasicWage(list.stream().map(t -> new BigDecimal(t.getBasicWage())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setDeductionOfAdvanceBonus(list.stream().map(t -> new BigDecimal(t.getDeductionOfAdvanceBonus())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setPaidInSalary(list.stream().map(t -> new BigDecimal(t.getPaidInSalary())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        dto.setNetWage(list.stream().map(t -> new BigDecimal(t.getNetWage())).reduce(BigDecimal.ZERO, BigDecimal::add).toString());
        return dto;
    }
}
